package com.shopx.auth.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.shopx.auth.bean.SysUrl;
import com.shopx.auth.dao.db1.SysRoleUrlDao;
import com.shopx.auth.dao.db1.SysUrlDao;
import com.shopx.auth.dao.db1.SysUserDao;
import com.shopx.auth.dao.db1.SysUserRoleDao;
import com.shopx.auth.model.SysRoleUrlModel;
import com.shopx.auth.model.SysUrlModel;
import com.shopx.auth.model.SysUserModel;
import com.shopx.auth.model.SysUserRoleModel;
import com.shopx.auth.service.ISysUrlService;
import com.shopx.base.constants.ResultCodeEnum;
import com.shopx.base.exception.OriginException;
import com.shopx.base.exception.ShopxException;
import com.shopx.base.service.ISysSeqService;
import com.shopx.base.service.base.BaseService;
import com.shopx.cmm.DTO.PageDTO;
import com.shopx.core.common.CommonConstant;
import com.shopx.core.utils.ClazzUtil;
import com.shopx.core.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


/**
 * @author lituo
 * @className: SysConfigServiceImpl
 * @description: 菜单服务
 * @date 2021/12/5 11:24 AM
 */
@Service
@Slf4j
public class SysUrlServiceImpl extends BaseService implements ISysUrlService {

  @Autowired
  private SysUrlDao urlDao;

  @Autowired
  private SysUserDao sysUserDao;

  @Autowired
  private ISysSeqService sysSeqService;

  @Autowired
  private SysRoleUrlDao roleUrlDao;

  @Autowired
  private SysUserRoleDao sysUserRoleDao;

  @Override
  public SysUrlModel selectByPrimaryKey(SysUrl sysUrl) throws ShopxException {
    if (sysUrl == null) {
      throw new ShopxException(ResultCodeEnum.PAR_NULL);
    }
    return urlDao.selectByPrimaryKey(sysUrl);
  }

  @Override
  public int insertSelective(SysUrl sysUrl) throws ShopxException {
    if (sysUrl == null) {
      throw new ShopxException(ResultCodeEnum.PAR_NULL);
    }
    //查询父菜单
    SysUrl su = new SysUrl();
    su.setUrlId(sysUrl.getParUrlId());
    SysUrlModel sum = urlDao.selectByPrimaryKey(su);
    if(sum==null){
      throw new OriginException("父菜单不存在");
    }

    String id = sysSeqService.getTabSeq("SysUrl", 6, null);
    sysUrl.setUrlId(id);
    sysUrl.setUrlLevel(sum.getUrlLevel()+1);
    sysUrl.setParUrlId(su.getUrlId());
    sysUrl.setCreateUserId(super.getLoginUserId());
    sysUrl.setState(CommonConstant.State.EFFECTIVE);
    int result = urlDao.insertSelective(sysUrl);
    if (result != 1) {
      throw new ShopxException(ResultCodeEnum.DB_ERROR);
    }
    return result;
  }

  @Override
  public int updateByPrimaryKeySelective(SysUrl sysUrl) throws ShopxException {
    if (sysUrl == null) {
      throw new ShopxException(ResultCodeEnum.PAR_NULL);
    }
    sysUrl.setUpdateUserId(super.getLoginUserId());
    int result = urlDao.updateByPrimaryKeySelective(sysUrl);
    if (result != 1) {
      throw new ShopxException(ResultCodeEnum.DB_ERROR);
    }
    return result;
  }

  @Override
  @Transactional(value = "db1", rollbackFor = Exception.class)
  public void deleteChkIds(SysUrlModel sysUrl) throws ShopxException {
    List<String> list = Arrays.asList(sysUrl.getIds().split(","));
    Map m = new HashMap();
    m.put("ids",list);
    urlDao.deleteBatch(m);
    roleUrlDao.deleteBatch(m);
  }

  @Override
  public int deleteByPrimaryKey(SysUrl sysUrl) throws ShopxException {
    if (sysUrl == null) {
      throw new ShopxException(ResultCodeEnum.PAR_NULL);
    }
    //查询是否拥有子菜单
    SysUrlModel sum = new SysUrlModel();
    sum.setParUrlId(sysUrl.getUrlId());
    List<SysUrlModel> parList = selectList(sum);
    if (parList != null && parList.size() > 0) {
      throw new OriginException("99999", "删除节点存在子节点，不允许删除");
    }
    //查询是否绑定了角色
    SysRoleUrlModel ru = new SysRoleUrlModel();
    ru.setUrlId(sysUrl.getUrlId());
    int count = roleUrlDao.selectCount(ru);
    if (count > 0) {
      throw new OriginException("99999", "删除节点已绑定角色，不允许删除");
    }
    //删除菜单
    int result = urlDao.deleteByPrimaryKey(sysUrl);
    if (result != 1) {
      throw new ShopxException(ResultCodeEnum.DB_ERROR);
    }
    return result;
  }

  @Override
  public int selectRoleHaveUrl(SysUrlModel sysUrlModel) throws ShopxException {
    if (sysUrlModel.getRoleCodes().length <= 0 || StringUtil.isEmpty(sysUrlModel.getUrl())) {
      throw new ShopxException(ResultCodeEnum.DB_ERROR);
    }
    Map<String, Object> map = new HashMap<String, Object>();
    if (sysUrlModel.getUrl().indexOf("?") > -1) {
      map.put("url", sysUrlModel.getUrl().substring(0, sysUrlModel.getUrl().indexOf("?")));
    } else {
      map.put("url", sysUrlModel.getUrl());
    }
    int count = urlDao.selectRoleHaveUrl(sysUrlModel);
    return count;
  }

  private int selectCount(SysUrlModel sysUrl) throws ShopxException {
    return urlDao.selectCount(sysUrl);
  }

  @Override
  public List<SysUrlModel> selectList(SysUrlModel sysUrl) throws ShopxException {
    List<SysUrlModel> list = urlDao.selectList(sysUrl);
    if (list.size() == 0) {
      return null;
    }
    List<SysUrlModel> modelList = new ArrayList<SysUrlModel>();
    for (SysUrlModel urlModel : list) {
      urlModel.setId(urlModel.getUrlId());
      urlModel.setPid(urlModel.getParUrlId());
      urlModel.setHasChildren(true);
      if (CommonConstant.UrlType.MENU.equals(urlModel.getUrlType())) {
        urlModel.setText(urlModel.getUrlName());
      } else {
        urlModel.setText(urlModel.getUrlName() + "【功能】");
      }
      urlModel.setExpanded(sysUrl.isExpanded());
      modelList.add(urlModel);
    }
    return modelList;
  }

  @Override
  public PageDTO<SysUrlModel> getListPage(SysUrlModel sysUrl) throws ShopxException {
    if (sysUrl == null) {
      throw new ShopxException(ResultCodeEnum.PAR_NULL);
    }
    PageDTO<SysUrlModel> pageDTO = new PageDTO<SysUrlModel>();
    pageDTO.setiTotalDisplayRecords(selectCount(sysUrl));
    pageDTO.setData(selectList(sysUrl));
    return pageDTO;
  }

  @Override
  public SysUrlModel createRoot() throws ShopxException {
    SysUrlModel urlModel = new SysUrlModel();
    urlModel.setPid("-1");
    urlModel.setId("0");
    urlModel.setText("目录");
    urlModel.setExpanded(true);
    return urlModel;
  }

  @Override
  public SysUrlModel selectOne(SysUrlModel url) throws ShopxException {
    List<SysUrlModel> list = urlDao.selectList(url);
    if (list == null || list.size() == 0) {
      return null;
    }
    SysUrlModel urlModel = list.get(0);
    urlModel.setId(urlModel.getUrlId());
    urlModel.setPid(urlModel.getParUrlId());
    urlModel.setText(urlModel.getUrlName());
    return urlModel;
  }

  /***
   * @description:获取用户对应的菜单
   * @author:lituo
   * @date:2021-01-05 11:06 AM
   * @return:net.sf.json.JSONArray
   */
  @Override
  public List<SysUrlModel> getUrlByUserId(String userId,String urlType,String cpId) throws ShopxException {
    //查询企业编号
    SysUserModel sysUser = new SysUserModel();
    sysUser.setUserId(userId);
    sysUser.setCpId(cpId);
    SysUserModel user = sysUserDao.selectByPrimaryKey(sysUser);
    if(user==null){
      throw new OriginException("99999","用户不存在，请重新登录");
    }
    SysUserRoleModel sysUserRole = new SysUserRoleModel();
    sysUserRole.setUserId(userId);
    sysUserRole.setCpId(cpId);
    List<SysUserRoleModel> list = sysUserRoleDao.selectList(sysUserRole);
    if (list == null || list.size() <= 0) {
      throw new ShopxException(ResultCodeEnum.USER_NOT_ROLE);
    }
    String[] roleCodes = new String[list.size()];
    for (int i = 0; i < list.size(); i++) {
      roleCodes[i] = list.get(i).getRoleCode();
    }
    SysUrlModel SysUrlModelParam = new SysUrlModel();
    SysUrlModelParam.setRoleCodes(roleCodes);
    SysUrlModelParam.setUrlType(urlType);
//    SysUrlModelParam.setCpId(user.getCpId());
    SysUrlModelParam.setCpId(cpId);
    List<SysUrlModel> urlList = urlDao.selectRoleUrl(SysUrlModelParam);
    return urlList;
  }

  @Override
  public JSONArray getUrlJsonByUserId(String userId,String urlType,String cpId) throws ShopxException {
    List<SysUrlModel> urlList = this.getUrlByUserId(userId,urlType,cpId);
    log.info(JSON.toJSONString(urlList));
    return integrationUrl(urlList);
  }


  /**
   * @param list
   * @description:整合菜单
   * @author:lituo
   * @date:2021-01-05 11:06 AM
   * @return:net.sf.json.JSONArray
   */
  private JSONArray integrationUrl(List<SysUrlModel> list) throws ShopxException {
    List<SysUrlModel> firstList = new ArrayList<SysUrlModel>();
    List<SysUrlModel> secondList = new ArrayList<SysUrlModel>();
    List<SysUrlModel> thirdList = new ArrayList<SysUrlModel>();
    JSONArray jsonArr = new JSONArray();
    for (SysUrlModel urlModal : list) {
      if (urlModal.getUrlLevel() == 1) {
        firstList.add(urlModal);
      }
      if (urlModal.getUrlLevel() == 2) {
        secondList.add(urlModal);
      }
      if (urlModal.getUrlLevel() == 3) {
        thirdList.add(urlModal);
      }
    }
    for (SysUrlModel fUrlModal : firstList) {
      // 第一层
      Map<String, Object> map = new HashMap<String, Object>();
      map.put("id", fUrlModal.getUrlId());
      map.put("title", fUrlModal.getUrlName());
      map.put("icon", "layui-icon layui-icon-file");
      map.put("href", "");
      if (StringUtil.isEmpty(fUrlModal.getUrl())) {
        map.put("type", 0);
        map.put("href", "");
      } else {
        map.put("type", 1);
        map.put("href", "".equals(fUrlModal.getUrl().trim()) ? "javascript:void(0)" : fUrlModal.getUrl());
      }
      //循环第一层，标记二级菜单
      List<Map<String, Object>> twoList = new ArrayList<Map<String, Object>>();
      for(SysUrlModel sUrlModal:secondList){
        if(sUrlModal.getParUrlId().equals(fUrlModal.getUrlId())){
          Map<String, Object> map2 = new HashMap<String, Object>();
          map2.put("id", sUrlModal.getUrlId());
          map2.put("title", sUrlModal.getUrlName());
          map2.put("icon", "layui-icon layui-icon-file");
          map2.put("href", "");
          if (StringUtil.isEmpty(sUrlModal.getUrl())) {
            map2.put("type", 0);
            map2.put("href", "");
          } else {
            map2.put("type", 1);
            map2.put("href", "".equals(sUrlModal.getUrl().trim()) ? "javascript:void(0)" : sUrlModal.getUrl());
          }
          List<Map<String, Object>> thList = new ArrayList<Map<String, Object>>();
          for(SysUrlModel tUrlModal:thirdList){
            if(tUrlModal.getParUrlId().equals(sUrlModal.getUrlId())){
              Map<String, Object> map3 = new HashMap<String, Object>();
              map3.put("id", tUrlModal.getUrlId());
              map3.put("title", tUrlModal.getUrlName());
              map3.put("icon", "layui-icon layui-icon-file");
              map3.put("href", "");
              if (StringUtil.isEmpty(tUrlModal.getUrl())) {
                map3.put("type", 0);
                map3.put("href", "");
              } else {
                map3.put("type", 1);
                map3.put("href", "".equals(tUrlModal.getUrl().trim()) ? "javascript:void(0)" : tUrlModal.getUrl());
              }
              thList.add(map3);
            }
          }
          if(thList!=null && thList.size()>0){
            map2.put("children",thList);
          }
          twoList.add(map2);
        }
      }
      if(twoList!=null && twoList.size()>0){
        map.put("children",twoList);
      }
      jsonArr.add(map);
    }
    return jsonArr;
  }

  @Override
  public List<SysUrlModel> queryParUrlNodeList(String parUrlId) throws ShopxException {
    SysUrlModel url = new SysUrlModel();
    url.setParUrlId(parUrlId);
    List<SysUrlModel> list = selectList(url);
    if (list == null || list.size() == 0) {
      throw new ShopxException(ResultCodeEnum.BUSI_NOT_EXISTS_RECORD);
    }
    return list;
  }

  private List<SysUrlModel> selectNodeList(SysUrlModel url, boolean isExpand) throws ShopxException {
    url.setState(CommonConstant.State.EFFECTIVE);
    List<SysUrlModel> list = urlDao.selectList(url);
    if (list.size() == 0) {
      return null;
    }
    List<SysUrlModel> modelList = new ArrayList<SysUrlModel>();
    for (SysUrl u : list) {
      modelList.add((SysUrlModel) ClazzUtil.copy(u, new SysUrlModel()));
    }
    for (SysUrlModel urlModel : modelList) {
      urlModel.setId(urlModel.getUrlId());
      urlModel.setPid(urlModel.getParUrlId());
      urlModel.setHasChildren(true);
      if (CommonConstant.UrlType.MENU.equals(urlModel.getUrlType())) {
        urlModel.setText(urlModel.getUrlName());
      } else {
        urlModel.setText(urlModel.getUrlName() + "【功能】");
      }
      urlModel.setExpanded(isExpand);
    }
    return modelList;
  }


  @Override
  public List<SysUrlModel> getCurUserUrl(){
    String userId = super.getLoginUserId();
    String cpId = super.getUserCpId();
    List<SysUrlModel> list = this.getUrlByUserId(userId,"2",cpId);
    return list;
  }


  @Override
  public String queryUrlNodeList(String parUrlId) throws ShopxException {
    SysUrlModel url = new SysUrlModel();
    if (parUrlId != null) {
      url.setParUrlId(parUrlId);
    }
    List<SysUrlModel> list = this.selectList(url);
    return integrationTreeUrl(list,"").toJSONString();
  }

  @Override
  public String queryEditUrlNodeList(SysUrlModel sysUrlModel) throws ShopxException{
    SysUrlModel url = new SysUrlModel();
    if (sysUrlModel.getParUrlId() != null) {
      url.setParUrlId(sysUrlModel.getParUrlId());
    }
    List<SysUrlModel> list = this.selectList(url);
    return integrationTreeUrl(list,sysUrlModel.getIds()).toJSONString();
  }

  /**
   * 验证是否存在记录
   * @param ids
   * @param a
   * @return
   */
  public boolean containsId(String ids, String a) {
    return Arrays.stream(ids.split(","))
            .map(String::trim) //Added to handle potential spaces around numbers.
            .anyMatch(id -> id.equals(a));
  }


  /**
   * @param list
   * @description:整合菜单
   * @author:lituo
   * @date:2021-01-05 11:06 AM
   * @return:net.sf.json.JSONArray
   */
  private JSONArray integrationTreeUrl(List<SysUrlModel> list,String ids) throws ShopxException {
    List<SysUrlModel> firstList = new ArrayList<SysUrlModel>();
    List<SysUrlModel> secondList = new ArrayList<SysUrlModel>();
    List<SysUrlModel> thirdList = new ArrayList<SysUrlModel>();
    List<SysUrlModel> fourList = new ArrayList<SysUrlModel>();
    JSONArray jsonArr = new JSONArray();
    for (SysUrlModel urlModal : list) {
      if (urlModal.getUrlLevel() == 1) {
        firstList.add(urlModal);
      }
      if (urlModal.getUrlLevel() == 2) {
        secondList.add(urlModal);
      }
      if (urlModal.getUrlLevel() == 3) {
        thirdList.add(urlModal);
      }
      if (urlModal.getUrlLevel() == 4) {
        fourList.add(urlModal);
      }
    }
    for (SysUrlModel fUrlModal : firstList) {
      // 第一层
      Map<String, Object> map = new HashMap<String, Object>();
      map.put("id", fUrlModal.getUrlId());
      if(!StringUtil.isEmpty(ids) && this.containsId(ids,fUrlModal.getUrlId())){
        if(CommonConstant.UrlType.FUNC.equals(fUrlModal.getUrlType())){
          map.put("checked", true);
        }else{
          //验证是否有下级菜单，有则不勾选，否则勾选
          boolean existsFlag = list.stream()
                  .anyMatch(model -> model.getParUrlId() != null && model.getParUrlId().equals(fUrlModal.getUrlId()));
          if(!existsFlag){
            //没有下级，且勾选了，则标记为勾选
            map.put("checked", true);
          }
        }
      }
      map.put("title", fUrlModal.getUrlName());
      map.put("icon", "layui-icon layui-icon-file");
      map.put("href", "");
      if (StringUtil.isEmpty(fUrlModal.getUrl())) {
        map.put("type", 0);
        map.put("href", "");
      } else {
        map.put("type", 1);
        map.put("href", "".equals(fUrlModal.getUrl().trim()) ? "javascript:void(0)" : fUrlModal.getUrl());
      }
      //循环第一层，标记二级菜单
      List<Map<String, Object>> twoList = new ArrayList<Map<String, Object>>();
      for(SysUrlModel sUrlModal:secondList){
        if(sUrlModal.getParUrlId().equals(fUrlModal.getUrlId())){
          Map<String, Object> map2 = new HashMap<String, Object>();
          map2.put("id", sUrlModal.getUrlId());
          if(!StringUtil.isEmpty(ids) && this.containsId(ids,sUrlModal.getUrlId())){
            if(CommonConstant.UrlType.FUNC.equals(sUrlModal.getUrlType())){
              map2.put("checked", true);
            }else{
              boolean existsFlag = list.stream()
                      .anyMatch(model -> model.getParUrlId() != null && model.getParUrlId().equals(sUrlModal.getUrlId()));
              if(!existsFlag){
                //没有下级，且勾选了，则标记为勾选
                map2.put("checked", true);
              }
            }
          }
          map2.put("title", sUrlModal.getUrlName());
          map2.put("icon", "layui-icon layui-icon-file");
          map2.put("href", "");
          if (StringUtil.isEmpty(sUrlModal.getUrl())) {
            map2.put("type", 0);
            map2.put("href", "");
          } else {
            map2.put("type", 1);
            map2.put("href", "".equals(sUrlModal.getUrl().trim()) ? "javascript:void(0)" : sUrlModal.getUrl());
          }
          List<Map<String, Object>> thList = new ArrayList<Map<String, Object>>();
          for(SysUrlModel tUrlModal:thirdList){
            if(tUrlModal.getParUrlId().equals(sUrlModal.getUrlId())){
              Map<String, Object> map3 = new HashMap<String, Object>();
              map3.put("id", tUrlModal.getUrlId());
              if(!StringUtil.isEmpty(ids) && this.containsId(ids,tUrlModal.getUrlId())){
                if(CommonConstant.UrlType.FUNC.equals(tUrlModal.getUrlType())){
                  map3.put("checked", true);
                }else{
                  //验证是否有下级菜单，有则不勾选，否则勾选
                  boolean existsFlag = list.stream()
                          .anyMatch(model -> model.getParUrlId() != null && model.getParUrlId().equals(tUrlModal.getUrlId()));
                  if(!existsFlag){
                    //没有下级，且勾选了，则标记为勾选
                    map3.put("checked", true);
                  }
                }
              }
              map3.put("title", tUrlModal.getUrlName());
              map3.put("icon", "layui-icon layui-icon-file");
              map3.put("href", "");
              if (StringUtil.isEmpty(tUrlModal.getUrl())) {
                map3.put("type", 0);
                map3.put("href", "");
              } else {
                map3.put("type", 1);
                map3.put("href", "".equals(tUrlModal.getUrl().trim()) ? "javascript:void(0)" : tUrlModal.getUrl());
              }

              List<Map<String, Object>> foList = new ArrayList<Map<String, Object>>();
              for(SysUrlModel fourUrlModal:fourList){
                if(fourUrlModal.getParUrlId().equals(tUrlModal.getUrlId())){
                  Map<String, Object> map4 = new HashMap<String, Object>();
                  map4.put("id", fourUrlModal.getUrlId());
                  if(!StringUtil.isEmpty(ids) && this.containsId(ids,fourUrlModal.getUrlId())){
                    map4.put("checked", true);
                  }
                  map4.put("title", fourUrlModal.getUrlName());
                  map4.put("icon", "layui-icon layui-icon-file");
                  map4.put("href", "");
                  if (StringUtil.isEmpty(fourUrlModal.getUrl())) {
                    map4.put("type", 0);
                    map4.put("href", "");
                  } else {
                    map4.put("type", 1);
                    map4.put("href", "".equals(fourUrlModal.getUrl().trim()) ? "javascript:void(0)" : fourUrlModal.getUrl());
                  }
                  foList.add(map4);
                }
              }
              if(foList!=null && foList.size()>0){
                map3.put("children",foList);
              }
              thList.add(map3);
            }
          }
          if(thList!=null && thList.size()>0){
            map2.put("children",thList);
          }
          twoList.add(map2);
        }
      }
      if(twoList!=null && twoList.size()>0){
        map.put("children",twoList);
      }
      jsonArr.add(map);
    }
    return jsonArr;
  }

  public static void main(String[] args) {
    String ids = "1,2,3,4";
    String a = "5";
    boolean s = Arrays.stream(ids.split(","))
            .map(String::trim) //Added to handle potential spaces around numbers.
            .anyMatch(id -> id.equals(a));
    System.out.println(s);
  }
}

